// 实现一个数据结构——环形队列，它是一种线性数据结构，
// 其操作表现基于 FIFO（先进先出）原则并且队尾被连接在队首之后以形成一个循环，
// 要求它可以利用之前用过的空间。
// 你的实现应该支持如下操作
// MyCircularQueue(k): 构造器，设置队列长度为 k 。
// Front: 从队首获取元素。如果队列为空，返回 -1 。
// Rear: 获取队尾元素。如果队列为空，返回 -1 。
// enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
// deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
// isEmpty(): 检查循环队列是否为空。
// isFull(): 检查循环队列是否已满。

class MyCircularQueue<T>{
    private elems: T[];// 元素列表
    private head: number;// 头指针
    private tail: number;// 尾指针
    private size: number;// 列表容量
    // 构造函数
    constructor(k: number) {
        this.size = k;
        this.elems = [];
        this.head = -1;
        this.tail = -1;
    }
    // 检查循环队列是否为空
    public isEmpty(): boolean {
        return this.head === -1;
    }
    // 检查循环队列是否已满
    public isFull(): boolean {
        return (this.tail + 1) % this.size === this.head;
    }
    // 从队首获取元素。如果队列为空，返回 -1 
    public Front(): T | number {
        if (this.isEmpty()) {
            return -1;
        }
        return this.elems[this.head];
    }
    // 获取队尾元素。如果队列为空，返回 -1
    public Rear(): T | number {
        if (this.isEmpty()) {
            return -1;
        }
        return this.elems[this.tail];
    }
    // 向循环队列插入一个元素。如果成功插入则返回真。
    public enQueue(value: T): boolean {
        if (this.isFull()) {
            return false;
        }
        // 注意，队列为空时记得初始化head指针
        if (this.isEmpty()) {
            this.head = 0;
        }
        this.tail = (this.tail + 1) % this.size;
        this.elems[this.tail] = value;
        return true;
    }
    // 从循环队列中删除一个元素。如果成功删除则返回真。
    public deQueue(): boolean {
        if (this.isEmpty()) {
            return false;
        }
        // 重要！当最后一个元素被删除时重置头尾指针
        if (this.head === this.tail) {
            this.head = -1;
            this.tail = -1;
            return true;
        }
        this.head = (this.head + 1) % this.size;
        return true;
    }
}

const q1 = new MyCircularQueue<string>(3);
console.log(q1.enQueue('1'));
console.log(q1.enQueue('2'));
console.log(q1.enQueue('3'));
console.log(q1.enQueue('4'));
console.log(q1.Rear());
console.log(q1.Front());
console.log(q1.isFull());
console.log(q1.deQueue());
console.log(q1.enQueue('4'));
console.log(q1.Rear());